<?php

namespace app\admin\controller\order;

use app\common\controller\Backend;
use ZipArchive;
use Exception;

/**
 * 项目订单主单
 *
 * @icon fa fa-circle-o
 */
class OrderReport extends Backend
{

    protected $noNeedRight = ['detail'];
    /**
     * OrderReport模型对象
     * @var \app\admin\model\order\Order
     */
    protected $model = null;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = new \app\admin\model\order\OrderMaster;
        $this->view->assign("payTypeList", $this->model->getPayTypeList());
        $this->view->assign("payStatusList", $this->model->getPayStatusList());
        $this->view->assign("statusList", $this->model->getStatusList());
        $this->view->assign("reportStatusList", $this->model->getReportStatusList());
    }



    /**
     * 默认生成的控制器所继承的父类中有index/add/edit/del/multi五个基础方法、destroy/restore/recyclebin三个回收站方法
     * 因此在当前控制器中可不用编写增删改查的代码,除非需要自己控制这部分逻辑
     * 需要将application/admin/library/traits/Backend.php中对应的方法复制到当前控制器,然后进行修改
     */

    /**
     * 查看
     *
     * @return string|Json
     * @throws \think\Exception
     * @throws DbException
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags', 'trim']);
        if (false === $this->request->isAjax()) {
            return $this->view->fetch();
        }
        //如果发送的来源是 Selectpage，则转发到 Selectpage
        if ($this->request->request('keyField')) {
            return $this->selectpage();
        }
        $user = $this->auth->getUserInfo();
        $groupIds = [];
        foreach ($this->auth->getGroupIds() as $key => $value) {
            $groupIds[] = $value;
        }
        $whereCustom = [];
        if (in_array(3, $groupIds, true) && count($groupIds) == 1) {
            // 医院账号
            $hospital = \app\admin\model\hospital\Hospital::where('admin_id', $user['id'])->find();
            if ($hospital) {
                $whereCustom = [
                    'order.hospital_id' => $hospital['id'],
                ];
            } else {
                $whereCustom = [
                    'order.hospital_id' => -1,
                ];
            }
        }
        [$where, $sort, $order, $offset, $limit] = $this->buildparams();
        $list = $this->model
            ->alias('order')
            ->field('order.*')
            ->where($where)
            ->where($whereCustom)
            ->where('pay_status', 1)
            ->where('order.status', '=', '30')
            ->join('user', 'order.user_id=user.id')
            ->with(['ordergoods', 'hospital', 'user', 'sale', 'orderTube'])
            ->order($sort, $order)
            ->paginate($limit);

        $result = ['total' => $list->total(), 'rows' => $list->items()];
        return json($result);
    }


    /**
     * 详情
     *
     * @param $ids
     * @return string
     * @throws DbException
     * @throws \think\Exception
     */
    public function detail($ids = null)
    {
        $row = $this->model->with(['orderReport'])->find($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $adminIds = $this->getDataLimitAdminIds();
        if (is_array($adminIds) && !in_array($row[$this->dataLimitField], $adminIds)) {
            $this->error(__('You have no permission'));
        }
        $this->view->assign('row', $row);
        return $this->view->fetch();
    }

    public function download($ids = null,$timeout=60)
    {
        $row = (new \app\admin\model\order\OrderReport)->find($ids);
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $remoteUrl = $row->report_image;
        // 1. 验证URL格式
        $parsedUrl = parse_url($remoteUrl);
        if (empty($parsedUrl['scheme']) || !in_array($parsedUrl['scheme'], ['http', 'https'])) {
            die("无效的远程URL，必须以 http:// 或 https:// 开头");
        }

        // 2. 处理文件名
        if (empty($fileName)) {
            // 从URL路径中解析文件名（如 https://example.com/file.zip → file.zip）
            $fileName = basename($parsedUrl['path'] ?? 'unknown_file');
            // 若解析失败，使用默认名
            if (empty($fileName)) {
                $fileName = 'download_' . date('YmdHis') . '.dat';
            }
        }
        $row->downloadstatus = 20;
        $row->save();

        $d = (new \app\admin\model\order\OrderReport)->where('order_id',$row->order_id)->where('downloadstatus',10)->find();
        if($d){
            $download_report_status = 20;
        }else{
            $download_report_status = 30;
        }
        $this->model->where('id',$row->order_id)->update(['download_report_status'=>$download_report_status]);
        $urlList = [$remoteUrl];
        // 3. 创建临时目录（ThinkPHP的runtime/temp目录，确保可写）
        $tempDir = RUNTIME_PATH . 'temp' . DIRECTORY_SEPARATOR . uniqid();
        if (!mkdir($tempDir, 0755, true) && !is_dir($tempDir)) {
            return $this->error('无法创建临时目录');
        }

        try {
            // 4. 下载远程文件到临时目录
            $localFiles = []; // 存储本地临时文件路径
            foreach ($urlList as $index => $url) {
                $url = trim($url);
                if (empty($url)) continue;

                // 获取文件名（从URL解析，如https://xxx.com/abc.jpg → abc.jpg）
                $fileName = basename(parse_url($url, PHP_URL_PATH));
                if (empty($fileName)) {
                    $fileName = "file_{$index}.dat"; // 默认文件名
                }

                // 本地临时文件路径
                $localPath = $tempDir . DIRECTORY_SEPARATOR . $fileName;

                // 下载远程文件（使用file_get_contents，也可替换为curl）
                // 注意：部分服务器可能禁止file_get_contents，需开启allow_url_fopen=On
                $fileContent = file_get_contents($url);
                if ($fileContent === false) {
                    throw new Exception("文件下载失败：{$url}");
                }

                // 保存到临时目录
                if (file_put_contents($localPath, $fileContent) === false) {
                    throw new Exception("文件保存失败：{$fileName}");
                }

                $localUrl = parse_url($url, PHP_URL_PATH);
                $urlInfo = \think\Db::name('attachment')->where('url',$url)->find();

                $localFiles[] = [
                    'local_path' => $localPath,
                    'file_name' => $urlInfo ? $urlInfo['filename'] : $fileName
                ];
            }

            if (empty($localFiles)) {
                throw new Exception("没有有效的文件可打包");
            }

            // 5. 创建ZIP压缩包
            $zipName = 'remote_files_' . date('YmdHis') . '.zip';
            $zipPath = $tempDir . DIRECTORY_SEPARATOR . $zipName;
            $zip = new ZipArchive();

            if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
                throw new Exception("无法创建ZIP文件");
            }

            // 添加文件到ZIP
            foreach ($localFiles as $file) {
                $zip->addFile($file['local_path'], $file['file_name']);
            }
            $zip->close();

            // 6. 输出ZIP文件给浏览器下载
            if (!file_exists($zipPath)) {
                throw new Exception("ZIP文件创建失败");
            }

            // 设置响应头
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . rawurlencode($zipName) . '"');
            header('Content-Length: ' . filesize($zipPath));
            readfile($zipPath);

            // 7. 注册清理函数（下载完成后删除临时文件）
            register_shutdown_function(function () use ($tempDir) {
                $this->deleteDir($tempDir);
            });
            exit;
        } catch (Exception $e) {
            // 出错时清理临时文件
            $this->deleteDir($tempDir);
            return $this->error($e->getMessage());
        }
    }

    public function downloadAll($ids = null)
    {
        $row = $this->model->with(['orderReport'])->where('id','in',$ids)->select();
        if (!$row) {
            $this->error(__('No Results were found'));
        }
        $urlList = [];
        foreach($row as $k => $d){
            foreach ($d['order_report'] as $key => $value) {
                $urlList[] = $value['report_image'];
            }
        }
    
        if (empty($urlList)) {
            return $this->error('文件URL格式错误');
        }

        // 2. 检查Zip扩展
        if (!class_exists('ZipArchive')) {
            return $this->error('服务器未安装Zip扩展，无法打包');
        }

        // 3. 创建临时目录（ThinkPHP的runtime/temp目录，确保可写）
        $tempDir = RUNTIME_PATH . 'temp' . DIRECTORY_SEPARATOR . uniqid();
        if (!mkdir($tempDir, 0755, true) && !is_dir($tempDir)) {
            return $this->error('无法创建临时目录');
        }

        try {
            // 4. 下载远程文件到临时目录
            $localFiles = []; // 存储本地临时文件路径
            foreach ($urlList as $index => $url) {
                $url = trim($url);
                if (empty($url)) continue;

                // 获取文件名（从URL解析，如https://xxx.com/abc.jpg → abc.jpg）
                $fileName = basename(parse_url($url, PHP_URL_PATH));
                if (empty($fileName)) {
                    $fileName = "file_{$index}.dat"; // 默认文件名
                }

                // 本地临时文件路径
                $localPath = $tempDir . DIRECTORY_SEPARATOR . $fileName;

                // 下载远程文件（使用file_get_contents，也可替换为curl）
                // 注意：部分服务器可能禁止file_get_contents，需开启allow_url_fopen=On
                $fileContent = file_get_contents($url);
                if ($fileContent === false) {
                    throw new Exception("文件下载失败：{$url}");
                }

                // 保存到临时目录
                if (file_put_contents($localPath, $fileContent) === false) {
                    throw new Exception("文件保存失败：{$fileName}");
                }

                $localUrl = parse_url($url, PHP_URL_PATH);
                $urlInfo = \think\Db::name('attachment')->where('url',$url)->find();

                $localFiles[] = [
                    'local_path' => $localPath,
                    'file_name' => $urlInfo ? $urlInfo['filename'] : $fileName
                ];
            }

            if (empty($localFiles)) {
                throw new Exception("没有有效的文件可打包");
            }

            // 5. 创建ZIP压缩包
            $zipName = 'remote_files_' . date('YmdHis') . '.zip';
            $zipPath = $tempDir . DIRECTORY_SEPARATOR . $zipName;
            $zip = new ZipArchive();

            if ($zip->open($zipPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
                throw new Exception("无法创建ZIP文件");
            }

            // 添加文件到ZIP
            foreach ($localFiles as $file) {
                $zip->addFile($file['local_path'], $file['file_name']);
            }
            $zip->close();

            // 6. 输出ZIP文件给浏览器下载
            if (!file_exists($zipPath)) {
                throw new Exception("ZIP文件创建失败");
            }

            $this->model->where('id','in',$ids)->update(['download_report_status' => 30]);

            // 设置响应头
            header('Content-Type: application/zip');
            header('Content-Disposition: attachment; filename="' . rawurlencode($zipName) . '"');
            header('Content-Length: ' . filesize($zipPath));
            readfile($zipPath);

            // 7. 注册清理函数（下载完成后删除临时文件）
            register_shutdown_function(function () use ($tempDir) {
                $this->deleteDir($tempDir);
            });
            exit;
        } catch (Exception $e) {
            // 出错时清理临时文件
            $this->deleteDir($tempDir);
            return $this->error($e->getMessage());
        }
    }

    /**
     * 递归删除目录及文件
     * @param string $dir 目录路径
     * @return bool
     */
    private function deleteDir($dir)
    {
        if (!is_dir($dir)) {
            return false;
        }
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file == '.' || $file == '..') {
                continue;
            }
            $filePath = $dir . DIRECTORY_SEPARATOR . $file;
            if (is_dir($filePath)) {
                $this->deleteDir($filePath);
            } else {
                unlink($filePath);
            }
        }
        return rmdir($dir);
    }
}
